package gwtBlocks.client.models;

/**
 * This model binds a single value held in this model to a single property in the domain object held by the contained
 * bean model.
 * 
 * @author hkrishna
 */
public abstract class PropertyBindingModel extends InputModel implements BindingModel
{
    private boolean _autoCommit;

    protected PropertyBindingModel(String key, BeanBindingModel parent, Converter propertyConverter)
    {
        super(key, parent);

        if (parent == null)
            throw new IllegalArgumentException(this + " needs a non null BeanBindingModel parent.");

        setConverter(propertyConverter);

        // In case this property model is created after the bean model value is set.
        parentValueChanged();
    }

    public void setParent(String key, CompositeModel parent)
    {
        if (!(parent instanceof BeanBindingModel))
            throw new IllegalArgumentException(this + " only accepts BeanBindingModel as parent. Argument:" + parent);

        super.setParent(key, parent);
    }

    public void parentValueChanged()
    {
        // Parent == Bean Model
        if (getParent().getValue() == null)
            setValue(null);
        else
            setValue(getPropertyValue());
    }

    protected void beforeNotifyChangeListeners()
    {
        if (_autoCommit)
            commit();
    }

    public void setAutoCommit(boolean autoCommit)
    {
        _autoCommit = autoCommit;
    }

    /**
     * This method will commit the value in this model to the bean model.
     */
    public void commit()
    {
        // Parent == Bean Model
        if (getParent().getValue() != null)
            setPropertyValue();
    }

    /**
     * This method will be generated by {@link BindingModelGenerator} during GWT's rebind phase.
     */
    protected abstract void setPropertyValue();

    /**
     * This method will be generated by {@link BindingModelGenerator} during GWT's rebind phase.
     */
    protected abstract Object getPropertyValue();
}
